package pl.edu.agh.mbc.server.session;

import java.util.LinkedHashMap;
import java.util.Random;
import java.util.Set;

import org.apache.log4j.Logger;

import pl.edu.agh.configs.UserObject;
import pl.edu.agh.mbc.commons.ISessionPool;

/**
 * 
 * @author wkedzior
 *
 */
public class SessionPool implements ISessionPool, Runnable {
	 private final static  LinkedHashMap<String, UserObject> MAP = new LinkedHashMap<String, UserObject>();
	 private int maxSessionCount;
	 private static final Logger LOG = Logger.getLogger(SessionPool.class);
	 public static final long PROLOG_SESSION_TIME =  1*1000;
	 private long maxNoActivitySessionPeriod;
	 
	 public SessionPool(int maxSessionCount, long maxNoActivitySessionPeriod ){
		 this.maxSessionCount = maxSessionCount;
		 this.maxNoActivitySessionPeriod= maxNoActivitySessionPeriod;
	 }
		 
	 
	public String createNewSession(String name, String password) throws Exception {
		if (MAP.size() < maxSessionCount){
			String key = generateUniqueKey( name, password);
			MAP.put(key, new UserObject(System.currentTimeMillis(), name,key ));
			return key;
		}else{
			throw new Exception("Session pool is overfilled!");
		}
	}

	/**
	 * Jezeli pobieramy cos z mapy, 
	 * oznacza to, ze user wykonuje jakas aktywnosc w aplikacji mobilnej.
	 * Wiec przedluzamy waznosc sesji.
	 */
	public UserObject getSessionByToken(String token) throws Exception {
		UserObject object = MAP.get(token);
		if (object!=null){
			object.setLogedInTimestamp(object.getLogedInTimestamp() + PROLOG_SESSION_TIME);
		}		
		return object;
	}
	
	/**
	 * Jakis kod z dupy, ktory zwraca nam...powiedzmy ze cos unikalnego :)
	 * @param userName
	 * @param password
	 * @return
	 */
	private String generateUniqueKey(String userName, String password){
		
		String uniqueToken = userName.concat(password);
		byte[] bytes = uniqueToken.getBytes();
		Random random = new Random();
		int num = random.nextInt(bytes.length - 1);
		long session = System.currentTimeMillis() / bytes[num];
		return String.valueOf( session);		
	}
	/**
	 * Troche to glupie roziwanie na czyszczenie sesji ...ale poki co ie mam
	 * nic innego na mysli :)
	 */
	public void run() {
		while(true){
			Set<String> keySet = MAP.keySet();
			for (String key: keySet){
				
				UserObject object = MAP.get( key);
				if (System.currentTimeMillis() - object.getLogedInTimestamp() > maxNoActivitySessionPeriod ){
					MAP.remove(key);
					LOG.debug("Removing object " + object.toString() + " from session.");
				}
			}
			
			try {
				Thread.sleep( 30 * 1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
	}
}
